/*
 * @Author: JYJ 
 * @Date: 2020-07-11 22:09:36 
 * @Desc: 网络模块
 */
namespace gf {
    /**
     * NetworkEngine的网络事件
     */
    export class NetEvent {
        /**
         * 断线重连成功
         */
        public static readonly SOCKET_CONNECT = "SOCKET_CONNECT";
        /**
         * 断线重连
         */
        public static readonly SOCKET_RECONNECT = "SOCKET_RECONNECT";
        /**
         * 开始断线重连
         */
        public static readonly SOCKET_START_RECONNECT = "SOCKET_START_RECONNECT";
        /**
         * socket断开连接
         */
        public static readonly SOCKET_CLOSE = "SOCKET_CLOSE";
        /**
         * socket连接错误
         */
        public static readonly SOCKET_ERROR = "SOCKET_ERROR";
        /**
         * 收到消息,监听这个消息就可以获得解析后的对象
         */
        public static readonly ON_MESSAGE = "ON_MESSAGE";
    }
    export class NetworkEngine extends gf.BaseClass {
        private needReconnect: boolean = false;
        private maxReconnectCount = 10;

        private reconnectCount: number = 0;
        private connectFlag: boolean;
        private host: string;
        private port: any;
        private socket: egret.WebSocket;
        private msg: BaseMsg;
        private isConnecting: boolean;
        public netEvent: GameEvent;

        public constructor() {
            super();
            this.netEvent = new GameEvent();
        }
        public static getInstance(): NetworkEngine {
            return super.getInstance();
        }
        /**
         * 添加事件监听
         */
        private addEvents() {
            this.socket.addEventListener(egret.ProgressEvent.SOCKET_DATA, this.onReceiveMessage, this);
            this.socket.addEventListener(egret.Event.CONNECT, this.onSocketOpen, this);
            this.socket.addEventListener(egret.Event.CLOSE, this.onSocketClose, this);
            this.socket.addEventListener(egret.IOErrorEvent.IO_ERROR, this.onSocketError, this);
        }

        /**
         * 移除事件监听
         */
        private removeEvents(): void {
            this.socket.removeEventListener(egret.ProgressEvent.SOCKET_DATA, this.onReceiveMessage, this);
            this.socket.removeEventListener(egret.Event.CONNECT, this.onSocketOpen, this);
            this.socket.removeEventListener(egret.Event.CLOSE, this.onSocketClose, this);
            this.socket.removeEventListener(egret.IOErrorEvent.IO_ERROR, this.onSocketError, this);
        }

        /**
         * 服务器连接成功
         */
        private onSocketOpen(): void {
            this.reconnectCount = 0;
            this.isConnecting = true;
            Log.log("连接服务器成功");
            if (this.connectFlag && this.needReconnect) {
                this.netEvent.dispatch(NetEvent.SOCKET_RECONNECT);
            } else {
                this.netEvent.dispatch(NetEvent.SOCKET_CONNECT);
            }
            this.connectFlag = true;
        }

        /**
         * 服务器断开连接
         */
        private onSocketClose(): void {
            this.isConnecting = false;

            if (this.needReconnect) {
                this.netEvent.dispatch(NetEvent.SOCKET_START_RECONNECT);
                this.reconnect();
            } else {
                this.netEvent.dispatch(NetEvent.SOCKET_CLOSE);
            }
        }

        /**
         * 服务器连接错误
         */
        private onSocketError(): void {
            if (this.needReconnect) {
                this.reconnect();
            } else {
                this.netEvent.dispatch(NetEvent.SOCKET_ERROR);
            }
            this.isConnecting = false;
        }

        /**
         * 收到服务器消息
         * @param e
         */
        private onReceiveMessage(e: egret.Event): void {
            this.msg.receive(this.socket);
        }

        /**
         * 初始化服务区地址
         * @param host IP
         * @param port 端口
         * @param msg 消息发送接受处理类
         */
        public initServer(host: string, port: any, msg: BaseMsg): void {
            this.host = host;
            this.port = port;
            this.msg = msg;
        }

        /**
         * 开始Socket连接
         */
        public connect(): void {
            this.socket = new egret.WebSocket();
            this.socket.type = egret.WebSocket.TYPE_BINARY;
            Log.log("WebSocket: " + this.host + ":" + this.port);
            this.addEvents();
            this.socket.connect(this.host, this.port);
        }

        /**
         * 重新连接
         */
        private reconnect(): void {
            this.closeCurrentSocket();
            this.reconnectCount++;
            if (this.reconnectCount < this.maxReconnectCount) {
                this.connect();
            } else {
                this.reconnectCount = 0;
                if (this.connectFlag) {
                    this.netEvent.dispatch(NetEvent.SOCKET_CLOSE);
                } else {
                    this.netEvent.dispatch(NetEvent.SOCKET_ERROR);
                }
            }
        }

        /**
         * 发送消息到服务器
         * @param msg
         */
        public send(msgID: number, msg: any): void {
            this.msg.send(this.socket, msgID, msg);
        }

        /**
         * 关闭Socket连接
         */
        public close(): void {
            this.connectFlag = false;
            this.closeCurrentSocket();
        }

        /**
         * 清理当前的Socket连接
         */
        private closeCurrentSocket() {
            this.removeEvents();
            this.socket.close();
            this.socket = null;
            this.isConnecting = false;
        }

        /**
         * Socket是否在连接中
         * @returns {boolean}
         */
        public get IsConnecting(): boolean {
            return this.isConnecting;
        }

        /**
         * Debug信息
         * @param str
         */
        private debugInfo(str: String): void {

        }

    }
}